package com.alibaba.citrus.cr.unified.inventory.repository.impl;

import com.alibaba.citrus.cr.common.annotation.EpochTransactional;
import com.alibaba.citrus.cr.common.annotation.RepositoryInvoker;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.lock.RedisLock;
import com.alibaba.citrus.cr.unified.inventory.contants.FeaturesKey;
import com.alibaba.citrus.cr.unified.inventory.repository.AllocateApplyOrderDetailReadRepository;
import com.alibaba.citrus.cr.unified.inventory.repository.AllocateApplyOrderDetailWriteRepository;
import com.alibaba.citrus.cr.unified.inventory.repository.AllocateApplyOrderWriteRepository;
import com.alibaba.citrus.cr.unified.inventory.utils.CodeUtil;
import com.alibaba.citrus.cr.unified.inventory.utils.InfoUtil;
import com.alibaba.citrus.cr.unified.inventory.utils.ToolUtil;
import com.alibaba.cz.base.model.enterprise.EmployeeSDO;
import com.alibaba.cz.base.tool.FeatureUtil;
import com.alibaba.cz.base.tool.feature.Features;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.enterprise.api.model.employee.EmployeeResponse;
import com.alibaba.cz.enterprise.api.service.EmployeeService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.contants.BcOrderConstants;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorder.dto.CreateAllocateApplyOrderResponse;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorder.dto.GetRequest;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorder.dto.LoadAllocateApplyOrderRequest;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorder.dto.NykCreateAllocateApplyOrderResponse;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorder.model.AllocateApplyOrder;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorder.service.AllocateApplyOrderService;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorderdetail.dto.AllocateApplyOrderDetailLoadListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorderdetail.dto.LoadAllocateApplyOrderDetailRequest;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorderdetail.dto.UpdateAllocateApplyOrderDetailResponse;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorderdetail.model.AllocateApplyOrderDetail;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorderdetail.service.AllocateApplyOrderDetailService;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.AllocateOrderDetailLoadListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.model.AllocateOrderDetail;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.service.AllocateOrderDetailService;
import com.epoch.app.crunifiedinventory.dto.response.AllocateApplyOrderGoodsDetailDTO;
import com.epoch.app.crunifiedinventory.model.dto.UpdateAllocateApplyOrderBySapSyncRequest;
import com.epoch.app.crunifiedinventory.model.dto.UpdateAllocateApplyOrderBySapSyncScItemDetail;
import com.epoch.app.crunifiedinventory.sdo.AllocateApplyOrderDetailSDO;
import com.epoch.app.crunifiedinventory.sdo.AllocateApplyOrderSDO;
import com.epoch.app.crunifiedinventory.sdo.enums.AllocateApplyOrderStatusEnum;
import com.epoch.app.crunifiedinventory.sdo.enums.AllocateStatusEnum;
import com.epoch.app.crunifiedinventory.sdo.enums.DocumentTypeEnum;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author heyu
 * @description
 */
@Component
public class AllocateApplyOrderWriteRepositoryImpl implements AllocateApplyOrderWriteRepository {
    private Log log = Log.getLogger(AllocateApplyOrderWriteRepositoryImpl.class);

    private static final String NULL_STRING = "";
    private static final String REGEX  = "^(0+)";


    @Resource
    private AllocateApplyOrderService allocateApplyOrderService;

    @Resource
    private AllocateApplyOrderDetailService allocateApplyOrderDetailService;

    @Resource
    private AllocateApplyOrderDetailWriteRepository allocateApplyOrderDetailWriteRepository;

    @Resource
    private AllocateApplyOrderDetailReadRepository allocateApplyOrderDetailReadRepository;

    @Resource
    private AllocateOrderDetailService allocateOrderDetailService;
    @DubboReference
    private EmployeeService employeeService;
    //SAP的默认创建人
    private static final String PIRFCUSER = "PIRFCUSER";

    @Override
    @EpochTransactional(appCode="bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    public String createAllocateApplyOrder(AllocateApplyOrderSDO allocateApplyOrderSDO) {
//        UUID uuid = UUID.randomUUID();
        AllocateApplyOrder allocateApplyOrder = new AllocateApplyOrder();
        BeanUtils.copyProperties(allocateApplyOrderSDO,allocateApplyOrder);
        allocateApplyOrder.setCode(CodeUtil.getPSTOCode());
//        allocateApplyOrder.setStatus((StringUtils.isBlank(allocateApplyOrderSDO.getFeatures()))?AllocateStatusEnum.DRAFT.getCode():
//                AllocateStatusEnum.COMPLETED.getCode());
        // key:nyk不存在状态为草稿（1），存在状态为已完成（5）
        Features features=Features.newFeatures(allocateApplyOrderSDO.getFeatures());
        allocateApplyOrder.setStatus((StringUtils.isBlank(features.get("key")))?AllocateStatusEnum.DRAFT.getCode():AllocateStatusEnum.COMPLETED.getCode());
        allocateApplyOrder.setCreator(allocateApplyOrderSDO.getOperator());
        //创建时,修改人和创建人一致
        allocateApplyOrder.setCreatorName(allocateApplyOrderSDO.getCreatorName());
        allocateApplyOrder.setModifierName(StringUtils.isBlank(allocateApplyOrderSDO.getModifierName()) ?
                allocateApplyOrderSDO.getCreatorName() : allocateApplyOrderSDO.getModifierName());
        allocateApplyOrder.setApplyOrgId(allocateApplyOrderSDO.getApplyOrgId());
        String orderTag = features.get("order_tag");
        Features bizFeatures = Features.newFeatures();
        if (StringUtils.isNotBlank(orderTag)) {
            bizFeatures.addFeature("order_tag",orderTag);
            allocateApplyOrder.setBizFeatures(bizFeatures.toString());
        }
        String bizUnit = features.get("biz_unit");
        if (StringUtils.isNotBlank(bizUnit)) {
            bizFeatures.addFeature("biz_unit",bizUnit);
            allocateApplyOrder.setBizFeatures(bizFeatures.toString());
        }
        log.info("底层插入调拨预报单创建入参createAllocateApplyOrder,allocateApplyOrder:{}"+ JSONObject.toJSONString(allocateApplyOrder));
        allocateApplyOrder.setGmt_create(allocateApplyOrderSDO.getGmtCreate());
        CreateAllocateApplyOrderResponse response = allocateApplyOrderService.createAllocateApplyOrder(allocateApplyOrder);
        if(null==response.getLastInsertId()){
            throw new RuntimeException("调拨预报单插入失败");
        }
        return allocateApplyOrder.getCode();
    }

    @Override
    @RepositoryInvoker
    @EpochTransactional(appCode="bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    public String nykCreateAllocateApplyOrder(AllocateApplyOrderSDO allocateApplyOrderSDO) {
//        UUID uuid = UUID.randomUUID();
        AllocateApplyOrder allocateApplyOrder = new AllocateApplyOrder();
        BeanUtils.copyProperties(allocateApplyOrderSDO,allocateApplyOrder);
        allocateApplyOrder.setCode(CodeUtil.getPSTOCode());
        allocateApplyOrder.setStatus((StringUtils.isBlank(allocateApplyOrderSDO.getFeatures()))?AllocateStatusEnum.DRAFT.getCode():
                AllocateStatusEnum.COMPLETED.getCode());
        allocateApplyOrder.setCreator(allocateApplyOrderSDO.getOperator());
        allocateApplyOrder.setUpdater(allocateApplyOrderSDO.getOperator());
        allocateApplyOrder.setApplyOrgId(allocateApplyOrderSDO.getApplyOrgId());
        log.info("nyk dao create AllocateApplyOrder ："+ JSONObject.toJSONString(allocateApplyOrder));
        allocateApplyOrder.setGmt_create(Objects.isNull(allocateApplyOrderSDO.getGmtCreate())?new Date():allocateApplyOrderSDO.getGmtCreate());
        NykCreateAllocateApplyOrderResponse response = allocateApplyOrderService.nykCreateAllocateApplyOrder(allocateApplyOrder);
        if(Objects.isNull(response) || StringUtils.isBlank(response.getLastInsertId())){
            log.error("AllocateApplyOrderWriteRepositoryImpl.nykCreateAllocateApplyOrder_fail");
            log.error("nykCreateAllocateApplyOrder create fail = allocateApplyOrder {} response {}",allocateApplyOrder,response);
        }
        return allocateApplyOrder.getCode();
    }

    @Override
    @EpochTransactional(appCode="bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void updateAllocateApplyOrder(AllocateApplyOrderSDO allocateApplyOrderSDO) {
        AllocateApplyOrder allocateApplyOrder = new AllocateApplyOrder();
        BeanUtils.copyProperties(allocateApplyOrderSDO,allocateApplyOrder);
        //TODO 这里会有影响 sap更新后就是 0了
        allocateApplyOrder.setUpdater(allocateApplyOrderSDO.getOperator());
        //更新调拨预报单
        allocateApplyOrderService.updateAllocateApplyOrder(allocateApplyOrder);
    }

    @Override
    @EpochTransactional(appCode="bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void update(AllocateApplyOrderSDO allocateApplyOrderSDO) {
        //更新调拨单
        this.updateAllocateApplyOrder(allocateApplyOrderSDO);
        //删除调拨详情
        allocateApplyOrderDetailWriteRepository.deleteDetailByOrderId(allocateApplyOrderSDO.getId());
        //插入详情
        List<AllocateApplyOrderDetailSDO> list = allocateApplyOrderSDO.getList();
        for (AllocateApplyOrderDetailSDO allocateApplyOrderDetailSDO:list){
            allocateApplyOrderDetailSDO.setIsDTC(Objects.isNull(allocateApplyOrderSDO.getIsDTC())?false:allocateApplyOrderSDO.getIsDTC());
            allocateApplyOrderDetailWriteRepository.createAllocateApplyOrderDetail(allocateApplyOrderDetailSDO);
        }
    }

    @Override
    @EpochTransactional(appCode="bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void sapCreate(AllocateApplyOrderSDO allocateApplyOrderSDO) {
        //更新主单
        this.updateAllocateApplyOrder(allocateApplyOrderSDO);
        //插入详情
        List<AllocateApplyOrderDetailSDO> list = allocateApplyOrderSDO.getList();
        Integer lineNo = 1;
        for (AllocateApplyOrderDetailSDO allocateApplyOrderDetailSDO :list){
            BigDecimal unitPrice = allocateApplyOrderDetailSDO.getUnitPrice();
            if (Objects.nonNull(unitPrice)){
                unitPrice = unitPrice.setScale(2, RoundingMode.HALF_UP);
            }
            AllocateApplyOrderDetailSDO allocateApplyOrderDetail = new AllocateApplyOrderDetailSDO();
            BeanUtils.copyProperties(allocateApplyOrderDetailSDO,allocateApplyOrderDetail);
            allocateApplyOrderDetail.setLineNo(lineNo);
            allocateApplyOrderDetail.setAllocateApplyOrderId(allocateApplyOrderSDO.getId().intValue());
            allocateApplyOrderDetail.setApplyQuantity(allocateApplyOrderDetailSDO.getApplyQuantity());
            allocateApplyOrderDetail.setUnitPrice(unitPrice);
            allocateApplyOrderDetail.setSubtotalMoney(allocateApplyOrderDetailSDO.getSubtotalMoney());
            allocateApplyOrderDetail.setCloseCode(allocateApplyOrderDetailSDO.getCloseCode());
            allocateApplyOrderDetail.setCloseReason(allocateApplyOrderDetailSDO.getCloseReason());
            if (AllocateApplyOrderStatusEnum.TO_BE_SUBMITTED.getCode().equals(allocateApplyOrderDetailSDO.getStatus())){
                allocateApplyOrderDetail.setStatus(AllocateApplyOrderStatusEnum.WAIT_ANSWER.getCode());
            }else{
                allocateApplyOrderDetail.setStatus(allocateApplyOrderDetailSDO.getStatus());
            }
            allocateApplyOrderDetail.setAllocateApplyOrderId(allocateApplyOrderSDO.getId().intValue());
            allocateApplyOrderDetail.setOutLineNo(allocateApplyOrderDetailSDO.getOutLineNo());
            allocateApplyOrderDetail.setIsDTC(Objects.isNull(allocateApplyOrderSDO.getIsDTC())?false:allocateApplyOrderSDO.getIsDTC());
            lineNo = lineNo+1;
            allocateApplyOrderDetailWriteRepository.createAllocateApplyOrderDetail(allocateApplyOrderDetail);
        }
    }

    @Override
    @EpochTransactional(appCode="bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void sapUpdate(AllocateApplyOrderSDO allocateApplyOrderSDO) {
        log.info("sapUpdate_request:{}",JSON.toJSONString(allocateApplyOrderSDO));
        //查调拨预报单数据
        String currentCreatorName = null;
        String currentModifierName = null;
//        if (!PIRFCUSER.equals(allocateApplyOrderSDO.getOperator())){
//            currentCreatorName = Optional.ofNullable(getEmployeeName(allocateApplyOrderSDO.getOperator())).orElse(allocateApplyOrderSDO.getOperator());
//            allocateApplyOrderSDO.setCreatorName(currentCreatorName);
//        }
        if (!PIRFCUSER.equals(allocateApplyOrderSDO.getOutModifier())){
            currentModifierName = Optional.ofNullable(getEmployeeName(allocateApplyOrderSDO.getOutModifier())).orElse(allocateApplyOrderSDO.getOutModifier());
            allocateApplyOrderSDO.setModifierName(currentModifierName);
        }
        //查找明细
        List<AllocateApplyOrderDetail> result = allocateApplyOrderDetailReadRepository.queryDetailByOrderId(allocateApplyOrderSDO.getId());
        Map<String,AllocateApplyOrderDetail> allocateApplyOrderGoodsDetailDTOMap = new HashMap<>();

        Integer lineNoMax =0;
        if (CollectionUtils.isNotEmpty(result)) {
            lineNoMax=result.stream().mapToInt(AllocateApplyOrderDetail::getLineNo).max().getAsInt();
            for (AllocateApplyOrderDetail allocateApplyOrderDetail : result) {
                allocateApplyOrderGoodsDetailDTOMap.put(allocateApplyOrderDetail.getGoodsCode(), allocateApplyOrderDetail);

            }
        }
        //删除明细
        //删除调拨详情
        allocateApplyOrderDetailWriteRepository.deleteDetailByOrderId(allocateApplyOrderSDO.getId());
        //插入详情
        List<AllocateApplyOrderDetailSDO> list = allocateApplyOrderSDO.getList();

        boolean isStatus = true;
        boolean isClosed = true;
        List<AllocateApplyOrderStatusEnum> detailStatusList = Lists.newArrayList();
        for (AllocateApplyOrderDetailSDO allocateApplyOrderDetailSDO :list){
            AllocateApplyOrderDetail allocateApplyOrderDetailOld = allocateApplyOrderGoodsDetailDTOMap.get(allocateApplyOrderDetailSDO.getScItemId().replaceAll(REGEX, NULL_STRING));
            BigDecimal unitPrice = allocateApplyOrderDetailSDO.getUnitPrice();
            if (Objects.nonNull(unitPrice)){
                unitPrice = unitPrice.setScale(2, RoundingMode.HALF_UP);
            }
            AllocateApplyOrderDetailSDO allocateApplyOrderDetail = new AllocateApplyOrderDetailSDO();
            if (Objects.isNull(allocateApplyOrderDetailOld)){
                BeanUtils.copyProperties(allocateApplyOrderDetailSDO,allocateApplyOrderDetail);
                allocateApplyOrderDetail.setLineNo(lineNoMax +1);
                allocateApplyOrderDetail.setAllocateApplyOrderId(allocateApplyOrderSDO.getId().intValue());
                allocateApplyOrderDetail.setApplyQuantity(allocateApplyOrderDetailSDO.getApplyQuantity());
                allocateApplyOrderDetail.setUnitPrice(unitPrice);
                allocateApplyOrderDetail.setSubtotalMoney(allocateApplyOrderDetailSDO.getSubtotalMoney());
                allocateApplyOrderDetail.setCloseReason(allocateApplyOrderDetailSDO.getCloseCode());
                if (StringUtils.isNotEmpty(allocateApplyOrderDetailSDO.getCloseCode())){
                    allocateApplyOrderDetail.setStatus(AllocateApplyOrderStatusEnum.CLOSED.getCode());
                }else{
                    allocateApplyOrderDetail.setStatus(allocateApplyOrderDetailSDO.getStatus());
                }
                allocateApplyOrderDetail.setAllocateApplyOrderId(allocateApplyOrderSDO.getId().intValue());
                allocateApplyOrderDetail.setOutLineNo(allocateApplyOrderDetailSDO.getOutLineNo());
                allocateApplyOrderDetail.setIsDTC(Objects.isNull(allocateApplyOrderSDO.getIsDTC())?false:allocateApplyOrderSDO.getIsDTC());
                lineNoMax++;
            }else{
                BeanUtils.copyProperties(allocateApplyOrderDetailOld,allocateApplyOrderDetail);
                allocateApplyOrderDetail.setScItemId(allocateApplyOrderDetailOld.getGoodsCode());
                allocateApplyOrderDetail.setTitle(allocateApplyOrderDetailOld.getGoodsName());
                allocateApplyOrderDetail.setApplyQuantity(allocateApplyOrderDetailSDO.getApplyQuantity());
                allocateApplyOrderDetail.setUnitPrice(unitPrice);
                allocateApplyOrderDetail.setSubtotalMoney(allocateApplyOrderDetailSDO.getSubtotalMoney());
                if (StringUtils.isNotEmpty(allocateApplyOrderDetailSDO.getCloseCode())){
                    allocateApplyOrderDetail.setStatus(AllocateApplyOrderStatusEnum.CLOSED.getCode());
                }else {
                    Integer replyQuantity = allocateApplyOrderDetailOld.getReplyQuantity() == null ? 0 : allocateApplyOrderDetailOld.getReplyQuantity();
                    Integer applyQuantity = allocateApplyOrderDetailSDO.getApplyQuantity() == null ? 0 : allocateApplyOrderDetailSDO.getApplyQuantity();
                    if (replyQuantity > 0){
                        if (replyQuantity >= applyQuantity){
                            allocateApplyOrderDetail.setStatus(AllocateApplyOrderStatusEnum.COMPLETED.getCode());
                        }else {
                            allocateApplyOrderDetail.setStatus(AllocateApplyOrderStatusEnum.PART_ANSWER.getCode());
                        }
                    }
                }
                allocateApplyOrderDetail.setCloseReason(allocateApplyOrderDetailSDO.getCloseCode());
                allocateApplyOrderDetail.setAllocateApplyOrderId(allocateApplyOrderSDO.getId().intValue());
                allocateApplyOrderDetail.setOutLineNo(allocateApplyOrderDetailSDO.getOutLineNo());
                allocateApplyOrderDetail.setIsDTC(Objects.isNull(allocateApplyOrderSDO.getIsDTC())?false:allocateApplyOrderSDO.getIsDTC());
                if (StringUtils.isNotEmpty(allocateApplyOrderDetailSDO.getRemark())){
                    allocateApplyOrderDetail.setRemark(allocateApplyOrderDetailSDO.getRemark());
                }
                if (Objects.nonNull(allocateApplyOrderDetailSDO.getCloseCode())&&Objects.nonNull(allocateApplyOrderDetailSDO.getCloseReason())){
                    allocateApplyOrderDetail.setIsClosed(1);
                }
            }
            if (!(AllocateApplyOrderStatusEnum.COMPLETED.getCode().equals(allocateApplyOrderDetail.getStatus())
                    ||AllocateApplyOrderStatusEnum.CLOSED.getCode().equals(allocateApplyOrderDetail.getStatus()))){
                isStatus = false;
            }
            if (!AllocateApplyOrderStatusEnum.CLOSED.getCode().equals(allocateApplyOrderDetail.getStatus())){
                isClosed = false;
            }

            detailStatusList.add(AllocateApplyOrderStatusEnum.of(allocateApplyOrderDetail.getStatus()));
            if (StringUtils.isNotBlank(currentModifierName)){
                allocateApplyOrderDetail.setModifierName(currentModifierName);
            }
            allocateApplyOrderDetailWriteRepository.createAllocateApplyOrderDetail(allocateApplyOrderDetail);
        }
        log.info("sapUpdate_detail_status_list:{}",JSON.toJSONString(detailStatusList));
        if (isStatus){
            if (isClosed){
                allocateApplyOrderSDO.setStatus(AllocateApplyOrderStatusEnum.CLOSED.getCode());
            }else{
                allocateApplyOrderSDO.setStatus(AllocateApplyOrderStatusEnum.COMPLETED.getCode());
            }
        }else {
            //判断主单状态
            if (detailStatusList.stream().anyMatch(AllocateApplyOrderStatusEnum.PART_ANSWER::equals)) {
                allocateApplyOrderSDO.setStatus(AllocateApplyOrderStatusEnum.PART_ANSWER.getCode());
            }else {
                allocateApplyOrderSDO.setStatus(AllocateApplyOrderStatusEnum.WAIT_ANSWER.getCode());
            }

        }
        //更新调拨单
        allocateApplyOrderSDO.setGmt_modified(new Date());
        this.updateAllocateApplyOrder(allocateApplyOrderSDO);
    }

    @Override
    @EpochTransactional(appCode="bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void cancel(AllocateApplyOrderSDO allocateApplyOrderSDO) {
        //更新调拨单
        this.updateAllocateApplyOrder(allocateApplyOrderSDO);
        if (Objects.nonNull(allocateApplyOrderSDO.getList())){
            //删除调拨详情
            allocateApplyOrderDetailWriteRepository.deleteDetailByOrderId(allocateApplyOrderSDO.getId());
            //插入详情
            List<AllocateApplyOrderDetailSDO> list = allocateApplyOrderSDO.getList();
            if (CollectionUtils.isNotEmpty(list)){
                for (AllocateApplyOrderDetailSDO allocateApplyOrderDetailSDO:list){
                    allocateApplyOrderDetailSDO.setIsDTC(Objects.isNull(allocateApplyOrderSDO.getIsDTC())?false:allocateApplyOrderSDO.getIsDTC());
                    allocateApplyOrderDetailWriteRepository.createAllocateApplyOrderDetail(allocateApplyOrderDetailSDO);
                }
            }
        }
    }

    /**
     * 根据销售调拨单同步请求来修改预报单 主要是修改 回复数量 和状态
     * 新增调拨单 直接加上数量
     * 更新调拨单, 第一次10 第二次是10  则变动量为0; 第一次10 第二次 15 则变动量为5 +5;
     *          第一次10  第二次 关闭, 则扣除此次的量
     *  需要知道 该行明细
     *      新增 ? 修改
     *       状态是否关闭
     */
    @Override
    public void updateByAllocateOrderWithLock(UpdateAllocateApplyOrderBySapSyncRequest request) {
        log.info("AllocateApplyOrderWriteRepositoryImpl_updateByAllocateOrderSaleSync_request:{}",
                JSON.toJSONString(request));
        //如果调拨单没有对应的预报单 跳过
        if (Objects.isNull(request) || request.getAllocateApplyOrderId() == null){
            log.info("AllocateApplyOrderWriteRepositoryImpl_updateByAllocateOrderSaleSync_has_not_applyOrder:{}",
                    JSON.toJSONString(request));
            return;
        }
        //加分布式锁
        String lockKey = StringUtils.isNotBlank(request.getOutAllocateApplyOrderCode()) ? request.getOutAllocateApplyOrderCode() : request.getAllocateApplyOrderId().toString();
        try (RedisLock lock = new RedisLock(BcOrderConstants.REDIS_CACHE_CODE(),"allocateApplyOrderUpdate_" + lockKey,5 * 60 * 1000,10 * 60 * 1000)){
            if (!lock.lock()){
                throw new FacadeException("OTS-03-005-00-15-096");
            }
            log.info("updateByAllocateOrderWithLock,threadId:{}",Thread.currentThread().getId());
            //明细参数不能为空
            if (CollectionUtils.isEmpty(request.getSyncScItemDetails())){
                return;
            }
            //查预报单 未查询到 返回
            LoadAllocateApplyOrderRequest orderRequest = new LoadAllocateApplyOrderRequest();
            orderRequest.setId(String.valueOf(request.getAllocateApplyOrderId()));
            AllocateApplyOrder applyOrder = allocateApplyOrderService.loadAllocateApplyOrder(orderRequest);
            if (applyOrder == null){
                return;
            }

            //循环请求明细 依次按货品查询预报单明细 增加/减少 回复量 确认量 是否关闭 状态
            for (UpdateAllocateApplyOrderBySapSyncScItemDetail detail : request.getSyncScItemDetails()) {
                AllocateApplyOrderDetailLoadListRequest allocateApplyOrderDetailLoadListRequest = new AllocateApplyOrderDetailLoadListRequest();
                allocateApplyOrderDetailLoadListRequest.setAllocateApplyOrderId(applyOrder.getId().intValue());
                allocateApplyOrderDetailLoadListRequest.setGoodsId(detail.getGoodsId());
                Result<List<AllocateApplyOrderDetail>> listResult = allocateApplyOrderDetailService.loadAllocateApplyOrderDetailList(allocateApplyOrderDetailLoadListRequest);
                log.info("AllocateOrderWriteRepositoryImpl.salesOrderSync.loadAllocateApplyOrderDetailList,allocateApplyOrderId:{},loadAllocateApplyOrderDetailList:{}", applyOrder.getId(), JSON.toJSONString(listResult));

                if (listResult != null && org.apache.commons.collections4.CollectionUtils.isNotEmpty(listResult.getResult())) {
                    AllocateApplyOrderDetail allocateApplyOrderDetail = listResult.getResult().get(0);
                    //是否关闭
                    allocateApplyOrderDetail.setIsClosed(detail.getClosed() ? 1 : 0);
                    //此次回复是关闭
                    if (Objects.equals(detail.getClosed(), Boolean.TRUE)) {
                        allocateApplyOrderDetail.setStatus(AllocateStatusEnum.CLOSED.getCode());
                        //预报拒绝原因来自closeCode
                        allocateApplyOrderDetail.setCloseReason(detail.getCloseCode());
                        allocateApplyOrderDetail.setCloseCode(detail.getCloseCode());
                        //调拨单明细不是创建时(即更新), 且之前的关闭状态不是已关闭状态, 需要去除调拨单明细第一次创建时回复的数量
                        if (!Boolean.TRUE.equals(detail.getIsCreate()) && !Boolean.TRUE.equals(detail.getOldClosed())){
                            allocateApplyOrderDetail.setReplyQuantity(InfoUtil.getValue(allocateApplyOrderDetail.getReplyQuantity(),detail.getOldQuantity()));
                        }
                    } else {
                        //调拨单之前处于关闭状态, 则这次数量变化就是现在调拨明细的数量
                        if (Boolean.TRUE.equals(detail.getOldClosed())){
                            detail.setQuantityChange(detail.getQuantity());
                        }
                        //原有回复量 + 调拨单数量变化(增加+ 减少-)
                        Integer v = InfoUtil.addReply(allocateApplyOrderDetail.getReplyQuantity(), detail.getQuantityChange());
                        allocateApplyOrderDetail.setReplyQuantity(v);
                        //原有预报单提报量
                        int amount = allocateApplyOrderDetail.getApplyQuantity() == null ? 0 : allocateApplyOrderDetail.getApplyQuantity();

                        //修改预报单的确认数量 原有确认量 + 调拨单确认数量变化
                        Integer c = InfoUtil.addReply(allocateApplyOrderDetail.getConfirmQuantity(), detail.getConfirmQuantityChange());
                        allocateApplyOrderDetail.setConfirmQuantity(c);
                        //如果 提报量 <= 回复量 预报单明细状态置为已完成
                        if (amount <= v) {
                            allocateApplyOrderDetail.setStatus(AllocateStatusEnum.COMPLETED.getCode());
                        } else {
                            //判断如果是跨公司类型状态不改变，其他类型状态改为部分回复
                            if (!DocumentTypeEnum.CROSS_COMPANY_BORROW_GOODS_ALLOCATION.getCode().equals(applyOrder.getType().toString())) {
                                allocateApplyOrderDetail.setStatus(AllocateStatusEnum.PART_ANSWER.getCode());
                            }
                        }
                        //去除关闭原因
                        allocateApplyOrderDetail.setCloseCode("");
                        allocateApplyOrderDetail.setCloseReason("");


                    }
                    allocateApplyOrderDetail.setGmt_modified(new Date());
                    allocateApplyOrderDetail.setReplyDate(new Date());
                    //生产日期
                    allocateApplyOrderDetail.setProductionTime(detail.getExpectedProduceDate());
                    UpdateAllocateApplyOrderDetailResponse updateAllocateApplyOrderDetailResponse = allocateApplyOrderDetailService.updateAllocateApplyOrderDetail(allocateApplyOrderDetail);
                    AllocateApplyOrderDetailLoadListRequest AllocateApplyOrderDetailLoadListRequest = new AllocateApplyOrderDetailLoadListRequest();
                    AllocateApplyOrderDetailLoadListRequest.setId(allocateApplyOrderDetail.getId());
                    Result<List<AllocateApplyOrderDetail>> result = allocateApplyOrderDetailService.loadAllocateApplyOrderDetailList(AllocateApplyOrderDetailLoadListRequest);
                    log.info("AllocateOrderWriteRepositoryImpl.salesOrderSync.setReplyQuantity,allocateApplyOrderDetailId:{},replyQuantity:{},success:{}", applyOrder.getId(), JSON.toJSONString(result),
                            JSON.toJSONString(updateAllocateApplyOrderDetailResponse));
                }
            }
            //更改预报主单的状态
            //再查询预调拨单详情
            List<AllocateApplyOrderGoodsDetailDTO> list = allocateApplyOrderDetailReadRepository.loadDetailByOrderId(applyOrder.getId());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(list)) {
                //是否完成态
                boolean isCompleted = true;
                for (AllocateApplyOrderGoodsDetailDTO allocateApplyOrderGoodsDetailDTO : list) {
                    if (!AllocateApplyOrderStatusEnum.COMPLETED.getCode().equals(allocateApplyOrderGoodsDetailDTO.getStatus()) && !AllocateApplyOrderStatusEnum.CLOSED.getCode().equals(allocateApplyOrderGoodsDetailDTO.getStatus())) {
                        isCompleted = false;
                    }
                }
                //子单所有都是完成态
                if (isCompleted) {
                    applyOrder.setStatus(AllocateStatusEnum.COMPLETED.getCode());
                    //完成时间
                    applyOrder.setCompleteTime(new Date());
                } else {
                    //判断如果是跨公司类型状态不改变，其他类型状态改为部分回复
                    if (!DocumentTypeEnum.CROSS_COMPANY_BORROW_GOODS_ALLOCATION.getCode().equals(applyOrder.getType().toString())) {
                        applyOrder.setStatus(AllocateStatusEnum.PART_ANSWER.getCode());
                    }
                }
                applyOrder.setGmt_modified(new Date());
                allocateApplyOrderService.updateAllocateApplyOrder(applyOrder);
            }
            updateAllocateApplyOrderLineId(request.getAllocateOrderCode() , request.getAllocateApplyOrderId());
        }
    }


    //更新调拨单里预报单行号的问题
    public void updateAllocateApplyOrderLineId(String code, Long allocateApplyOrderId) {
        if (StringUtils.isBlank(code) || allocateApplyOrderId == null) {
            return;
        }
        AllocateOrderDetailLoadListRequest detailLoadListRequest = new AllocateOrderDetailLoadListRequest();
        detailLoadListRequest.setAllocateOrderCode(code);
        detailLoadListRequest.setLimit(1000);
        Result<List<AllocateOrderDetail>> result = allocateOrderDetailService.loadAllocateOrderDetailList(detailLoadListRequest);
        if (result == null || org.apache.commons.collections4.CollectionUtils.isEmpty(result.getResult())) {
            return;
        }
        //获取预报单明细
        AllocateApplyOrderDetailLoadListRequest allocateApplyOrderDetailLoadListRequest = new AllocateApplyOrderDetailLoadListRequest();
        allocateApplyOrderDetailLoadListRequest.setAllocateApplyOrderId(allocateApplyOrderId.intValue());
        allocateApplyOrderDetailLoadListRequest.setLimit(1000);
        Result<List<AllocateApplyOrderDetail>> listResult = allocateApplyOrderDetailService.loadAllocateApplyOrderDetailList(allocateApplyOrderDetailLoadListRequest);
        log.info("AllocateApplyOrderWriteRepositoryImpl_updateAllocateApplyOrderLineId_load:{}",JSON.toJSONString(listResult));
        if (listResult == null || org.apache.commons.collections4.CollectionUtils.isEmpty(listResult.getResult())) {
            return;
        }
        //找到 并更新行号
        for (AllocateOrderDetail detail : result.getResult()) {
            List<AllocateApplyOrderDetail> collect = listResult.getResult().stream().filter(x -> Objects.equals(x.getGoodsId(), detail.getScItemId())).collect(Collectors.toList());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(collect)) {
                AllocateApplyOrderDetail allocateApplyOrderDetail = collect.get(0);
                detail.setAllocateApplyOrderLineId(allocateApplyOrderDetail.getLineNo() == null ? null : allocateApplyOrderDetail.getLineNo().toString());
                detail.setGmt_modified(new Date());
                if (StringUtils.isNotBlank(allocateApplyOrderDetail.getBizFeatures())){
                    Map<String, String> bizFeaturesMap = FeatureUtil.fromString(allocateApplyOrderDetail.getBizFeatures());
                    Map<String, String> detailBizFeaturesMap = FeatureUtil.fromString(detail.getBizFeatures());
                    if (StringUtils.isNotBlank(bizFeaturesMap.get(FeaturesKey.BIZ_UNIT_RATIO))){
                        detailBizFeaturesMap.put(FeaturesKey.BIZ_UNIT_RATIO,bizFeaturesMap.get(FeaturesKey.BIZ_UNIT_RATIO));
                    }
                    if (StringUtils.isNotBlank(bizFeaturesMap.get(FeaturesKey.PLAN_SUGGEST_QUANTITY))){
                        detailBizFeaturesMap.put(FeaturesKey.PLAN_SUGGEST_QUANTITY,bizFeaturesMap.get(FeaturesKey.PLAN_SUGGEST_QUANTITY));
                    }
                    if (StringUtils.isNotBlank(bizFeaturesMap.get(FeaturesKey.ALGORITHM_SUGGEST_QUANTITY))){
                        detailBizFeaturesMap.put(FeaturesKey.ALGORITHM_SUGGEST_QUANTITY,bizFeaturesMap.get(FeaturesKey.ALGORITHM_SUGGEST_QUANTITY));
                    }
                    if (StringUtils.isNotBlank(bizFeaturesMap.get(FeaturesKey.APPLY_DEVIATION_REASON))){
                        detailBizFeaturesMap.put(FeaturesKey.APPLY_DEVIATION_REASON,bizFeaturesMap.get(FeaturesKey.APPLY_DEVIATION_REASON));
                    }
                    if (StringUtils.isNotBlank(bizFeaturesMap.get(FeaturesKey.ADVANCE_APPLY_QUANTITY))){
                        detailBizFeaturesMap.put(FeaturesKey.ADVANCE_APPLY_QUANTITY,bizFeaturesMap.get(FeaturesKey.ADVANCE_APPLY_QUANTITY));
                    }
                    if (MapUtils.isNotEmpty(detailBizFeaturesMap)){
                        detail.setBizFeatures(FeatureUtil.toString(detailBizFeaturesMap));
                    }
                }
                allocateOrderDetailService.updateAllocateOrderDetail(detail);
            }
        }

    }
    /**
     * 根据工号获取姓名
     * @param workId
     * @return
     */
    private String getEmployeeName(String workId){
        if (StringUtils.isBlank(workId)){
            return null;
        }
        com.alibaba.cz.base.tool.result.Result<List<EmployeeResponse>> employees = employeeService.getEmployeesByWorkId(workId);
        log.info("syncAllocateOrder_getEmployeesByWorkId:{}",JSON.toJSONString(employees));
        if (employees != null && org.apache.commons.collections4.CollectionUtils.isNotEmpty(employees.getResult())){
            return Optional.ofNullable(employees.getResult().get(0)).map(EmployeeResponse::getEmployeeSDO).map(EmployeeSDO::getName).orElse(null);
        }
        return null;
    }
}
